//
// Created by mio on 25-4-29.
//

#ifndef SIGCONNECTION_H
#define SIGCONNECTION_H

#include <map>
#include <vector>

#include "define.h"
#include "../Net/TcpConnection.h"

class SigConnection : public TcpConnection
{
public:
    SigConnection(TaskScheduler* scheduler, int socket);
    ~SigConnection();

    /**
     * @brief 检查连接是否仍然存活 (即状态不是 CLOSE)。
     * @return 如果连接未关闭则返回 true，否则返回 false。
     *
    bool IsAlive()  { return state_ != CLOSE; }
    /**
     * @brief 检查客户端是否尚未加入任何房间或进行身份验证 (即状态是 NONE)。
     * @return 如果客户端处于初始未加入状态则返回 true，否则返回 false。
     */
    bool IsNoJoin() { return state_ == NONE; }
    /**
     * @brief 检查客户端是否处于空闲状态 (已加入但未推流或拉流)。
     * @return 如果客户端处于空闲状态则返回 true，否则返回 false。
     */
    bool IsIdle()   { return state_ == IDLE; }
    /**
     * @brief 检查客户端是否处于忙碌状态 (即正在推流 PUSHER 或拉流 PULLER)。
     * @return 如果客户端正在推流或拉流则返回 true，否则返回 false。
     */
    bool IsBusy()   { return state_ == PUSHER || state_ == PULLER; }
    /**
     * @brief 处理连接断开后的清理逻辑。
     *        通常在 TcpConnection 的 CloseCallback 中被调用。
     *        主要工作委托给 Clear() 方法。
     */
    void DisConnected();
    /**
     * @brief 添加一个关联的客户端标识符到 objectes_ 列表。
     *        "custom" 指的是与当前连接产生交互的其他客户端的标识符 (code_)。
     *        例如，如果 A 拉 B 的流，A 的 objectes_ 会添加 B 的 code_，B 的 objectes_ 会添加 A 的 code_。
     * @param code 要添加的对方客户端的唯一标识符。
     */
    void AddCustom(const std::string& code);
    /**
     * @brief 从 objectes_ 列表中移除一个关联的客户端标识符。
     *        如果移除后 objectes_ 列表为空，可能会将当前连接状态设置回 IDLE。
     * @param code 要移除的对方客户端的唯一标识符。
     * @note 原方法名 RmoveCustom 有拼写错误，已在实现中假设为 RemoveCustom 的意图。
     */
    void RmoveCustom(const std::string& code);
    /**
     * @brief 获取当前连接的客户端角色状态 (PUSHER, PULLER, IDLE, etc.)。
     * @return RoleState 枚举值，表示当前客户端的角色状态。
     */
    RoleState GetRoleState() const          { return state_; }
    /**
     * @brief 获取当前连接的客户端唯一标识符 (ID/code)。
     * @return 客户端的唯一标识符字符串。
     */
    std::string GetCode() const             { return code_; } // 获取标识符
    /**
     * @brief 获取当前连接关联的流地址 (通常是推流端生成的 RTMP 等流地址)。
     * @return 流地址字符串。如果不是推流端或流未创建，则为空。
     */
    std::string GetStreamAddres() const     { return streamAddres_; }

protected:
    bool OnRead(BufferReader& buffer);
    void HandleMessage(BufferReader& buffer);
    void Clear();

private:
    /* --- 各种信令消息的具体处理函数 --- */
    /**
     * @brief 处理客户端的 JOIN (加入/注册) 请求。
     * @param data 指向 packet_head 的指针，实际应转型为 Join_body。
     */
    void HandleJoin(const packet_head* data);
    /**
     * @brief 处理客户端的 OBTAINSTREAM (请求获取/拉取流) 请求。
     * @param data 指向 packet_head 的指针，实际应转型为 ObtainStream_body。
     */
    void HandleObtainStream(const packet_head* data);
    /**
     * @brief 处理客户端的 CREATESTREAM (创建流，通常是推流端上报已创建的流信息) 请求。
     * @param data 指向 packet_head 的指针，实际应转型为 CreateStreamReply_body (因其携带流地址)。
     */
    void HandleCreateStream(const packet_head* data);
    /**
     * @brief 处理客户端的 DELETESTREAM (删除/停止流) 请求。
     * @param data 指向 packet_head 的指针，实际应转型为 DeleteStream_body。
     */
    void HandleDeleteStream(const packet_head* data);
    /**
     * @brief 处理其他类型的消息，主要是鼠标和键盘等控制事件的转发。
     * @param data 指向 packet_head 的指针，具体类型根据 cmd 字段判断。
     */
    void HandleOtherMessage(const packet_head* data);

    /* --- 核心业务逻辑执行函数 (被 HandleXXX 系列函数调用) --- */
    /**
     * @brief 执行获取流 (OBTAINSTREAM) 的核心业务逻辑。
     *        处理客户端请求拉取另一个客户端流的完整流程。
     * @param data 指向 packet_head 的指针，实际类型为 ObtainStream_body。
     */
    void DoObtainStream(const packet_head* data);
    /**
     * @brief 执行创建流（实际上是处理推流端上报流创建结果，并通知相关拉流端）的核心业务逻辑。
     * @param data 指向 packet_head 的指针，实际类型为 CreateStreamReply_body（因其包含了流地址）。
     */
    void DoCreateStream(const packet_head* data);

private:
    RoleState state_;                       // 当前连接的客户端角色状态 (IDLE, PUSHER, PULLER, NONE, CLOSE)
    std::string code_;                      // 当前连接的客户端唯一标识符 (例如用户ID或房间ID)
    std::string streamAddres_;              // 如果当前客户端是推流端 (PUSHER)，这里存储其推流的媒体流地址 (如 RTMP 地址)
    TcpConnectionPtr conn_ = nullptr;       // 如果当前客户端是拉流端 (PULLER)，这里存储其正在拉取的推流端 (PUSHER) 的 SigConnection 实例的 TcpConnectionPtr。
                                                // 主要用于将 PULLER 发送的控制消息（如鼠标、键盘事件）转发给 PUSHER。
    std::vector<std::string> objectes_;     // 存储与当前 SigConnection 实例有直接交互关系的其他 SigConnection 实例的 code_。
                                                // - 对于 PUSHER: 存储所有正在拉取其流的 PULLER 客户端的 code_。
                                                // - 对于 PULLER: 通常存储其正在拉取的那个 PUSHER 客户端的 code_ (一般只有一个)。
                                                // 用于在连接断开或状态改变时通知相关方。
};

#endif //SIGCONNECTION_H
